﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Utils.ControlToLoad;
using Utils.Web;
using DAL;
using Utils.Exceptions;
using System.Collections.Generic;

namespace Prototype1
{
    public partial class ControlExpenseLine : ControlWithDDlAndId
    {
        private const String DDL_FIRST_ELEM = "Select...";

        protected void Page_Load(object sender, EventArgs e)
        {
            //ExpenseLine l = ExpenseLine.Get(new Guid("23b58779-486d-43b7-a3b9-aa43b031fa83"));

            //this.ControlId = new Guid("23b58779-486d-43b7-a3b9-aa43b031fa83");
            if (this.ControlId == null)
            {
                this.ControlId = Guid.NewGuid();
            }
            
            if (!this.ReadOnly)
                this.LoadIfNotReadOnly();
            
        }

        private void LoadIfNotReadOnly()
        {
            if (!IsPostBack)
                this.Bind_ddl_ExpenseTypes();
            using (DataAccessDataContext dc = new DataAccessDataContext())
            {
                var result = from t in dc.Templates
                             select t;
                IEnumerator templates = result.GetEnumerator();
                while (templates.MoveNext())
                {
                    String controlName = ((Template)(templates.Current)).EditControl;
                    Control c = Page.LoadControl("EditControls\\" + controlName);
                    this.ph_ControlHolder.Controls.Add(c);
                }
            }
        }

        public bool ReadOnly
        {
            get
            {
                if (ViewState["ReadOnly"] != null)
                    return (bool)ViewState["ReadOnly"];
                else
                    return false;
            }
            set { ViewState["ReadOnly"] = value; }
        }

        //id do expenseType seleccionado
        public Guid? IdR
        {
            get
            {
                if (ViewState["IdR"] != null)
                    return (Guid)ViewState["IdR"];
                else
                    return null;
            }
            set { ViewState["IdR"] = value; }
        }
        private void Bind_ddl_ExpenseTypes()
        {
            this.ddl_ExpenseTypes.DataSource = ExpenseType.GetAll();
            this.ddl_ExpenseTypes.DataBind();
            this.ddl_ExpenseTypes.Items.Insert(0, DDL_FIRST_ELEM);
        }

        private void LoadFields(ExpenseLine el)
        {
            this.Calendar.SelectedDate = el.Date.Value;
            this.tb_description.Text = el.Description;
            this.tb_Justification.Text = el.Justification;
            this.tb_expReportId.Text = el.ExpenseReportId.ToString();
        }

        public override void DataBind()
        {
            base.DataBind();

            ExpenseLine el = ExpenseLine.Get(this.ControlId.Value);
            if (el != null)
            {
                this.LoadFields(el);
                this.SelectedControlName = this.BuildSelectedControlString(el.ExpenseType.Template.EditControl);
                this.IdR = el.ExpenseType.Id;
            }

            //if (this.ControlId != null)
            //{
            //    ExpenseLine el = ExpenseLine.Get(this.ControlId.Value);
            //    if (el != null)
            //    {
            //        //this.Calendar.SelectedDate = el.Date;
            //        this.tb_description.Text = el.Description;
            //        this.tb_Justification.Text = el.Justification;
            //        this.tb_expReportId.Text = el.ExpenseReportId.ToString();
            //    }
            //}
        }

        protected void ddl_ExpenseTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            //falta verificar se este valor é o que é bom.
            if (this.ddl_ExpenseTypes.SelectedValue.Equals(DDL_FIRST_ELEM))
                return;
            this.IdR = new Guid(this.ddl_ExpenseTypes.SelectedValue);
            //using (DataAccessDataContext dc = new DataAccessDataContext())
            //{
            //var query = from t in dc.ExpenseTypes
            //            where t.Id.Equals(this.IdR)
            //            select t.Template;
            //Template temp = query.Single<Template>();
            IQueryable<Template> temp = ExpenseType.GetTemplate(this.IdR.Value);
            Template template = temp.First<Template>();

            this.SelectedControlName = this.BuildSelectedControlString(template.EditControl);
            //Control c = Page.LoadControl(this.SelectedControlName);
            //((IControlToLoadRW)c).Bind(this.ControlId, this.IdR);
            //this.ph_ControlHolder.Controls.Clear();
            //this.ph_ControlHolder.Controls.Add(c);

            //}
        }

        private String BuildSelectedControlString(String s)
        {
            return "EditControls\\" + s;
        }

        private void SaveEditControlData()
        {
            if (string.IsNullOrEmpty(this.SelectedControlName))
            {
                return;
            }
            Type t = Page.LoadControl(this.SelectedControlName).GetType();
            IEnumerator phControls = this.ph_ControlHolder.Controls.GetEnumerator();
            while (phControls.MoveNext())
            {
                if (t == phControls.Current.GetType())
                {
                    //Prototype1.EditControls.ControlTemplateSimple c =
                    //    (Prototype1.EditControls.ControlTemplateSimple)phControls.Current;
                    //Prototype1.EditControls.ControlTemplateDislocations c = 
                    //    (Prototype1.EditControls.ControlTemplateDislocations)phControls.Current;
                    IControlToLoadRW ictrw = (IControlToLoadRW)phControls.Current;
                    ictrw.Bind(this.ControlId.Value, this.IdR.Value);
                    ((IControlToLoadRW)phControls.Current).Save();

                }
            }
        }
        public void Save()
        {
            ExpenseLine expl = new ExpenseLine();
            String description = this.tb_description.Text;
            String justification = this.tb_Justification.Text;
            DateTime date = this.Calendar.SelectedDate;
            String expReportId = this.tb_expReportId.Text;
            //verificar se existe um report com este ID..
            expl.ExpenseReportId = new Guid(expReportId);
            expl.Date = date;
            if (this.tb_Justification.Visible)
                expl.Justification = justification;
            expl.Id = this.ControlId.Value;
            //o this.IdR pode ainda não estar bem se for clickado no botão de submit sem ter nenhum seleccionado
            expl.ExpenseTypeId = this.IdR.Value;
            expl.Description = description;
            expl.Save();
            //using (DataAccessDataContext da = new DataAccessDataContext())
            //{
            //    da.ExpenseLines.InsertOnSubmit(expl);
            //    da.SubmitChanges();
            //}
            this.SaveEditControlData();
        }

        private void LoadEditControl()
        {
            if (string.IsNullOrEmpty(this.SelectedControlName))
            {
                this.ph_ControlHolder.Controls.Clear();
                return;
            }
            //mal feito, devia ser carregado o tipo a partir da string para evitar este LoadControl
            Type t = Page.LoadControl(this.SelectedControlName).GetType();

            //se o controlo não for o selecionado é removido
            IEnumerator phControls = this.ph_ControlHolder.Controls.GetEnumerator();
            List<object> toRemove = new List<object>();
            while (phControls.MoveNext())
            {
                if (t != phControls.Current.GetType())
                    toRemove.Add(phControls.Current);
                else
                {
                    ((IControlToLoadRW)(phControls.Current)).Bind(this.ControlId.Value, this.IdR.Value);
                    ((IControlToLoadRW)(phControls.Current)).BindControls(this.ControlId.Value);
                }
            }
            foreach (object o in toRemove)
            {
                this.ph_ControlHolder.Controls.Remove((Control)o);
            }
        }

        //Ver nas configurações da parte comum o que tem que estar visível ou não
        private void LoadControlMetadata()
        {
            if (!this.IdR.HasValue)
                return;
            ExpenseType expType = ExpenseType.Get(this.IdR.Value);
            if (expType.RequiresJust.Value)
            {
                this.lb_Justification.Visible = true;
                this.tb_Justification.Visible = true;
            }
            else
            {
                this.lb_Justification.Visible = false;
                this.tb_Justification.Visible = false;
            }
        }

        //aqui só deixo ficar aquele que está selecionado. Se não estiver nenhum selecionado n fica nenhum.
        protected override void OnPreRender(EventArgs ea)
        {
            base.OnPreRender(ea);
            this.DataBind();
            this.LoadControlMetadata();
            this.LoadEditControl();
        }
    }
}
